// storageManager.js - 存储管理工具
// 提供单例模式的存储管理器，用于统一管理wx.setStorageSync和wx.getStorageSync，以及缓存空间检查和清理操作
let instance = null;

/**
 * 存储管理类
 * 负责统一管理存储操作、缓存空间检查和清理操作
 */
class StorageManager {
  constructor() {
    // 定义需要保留的原始字段（在清理单词同步数据时）
    this.ORIGINAL_WORD_FIELDS = ['id', 'english', 'chinese', 'categories', 'groups'];
    
    // 定义缓存键名
    this.STORAGE_KEYS = {
      WORD_DICTIONARY: 'wordDictionary',
      WORD_BOOKS: 'wordBooks',
      WORD_DICTIONARY: 'wordDictionary',
      WORD_CATEGORIES: 'wordCategories',
      PRONUNCIATION_SETTINGS: 'pronunciationSettings',
      LEARNING_DATA: 'learningData',
      USER_SETTINGS: 'userSettings',
      TODAY_TASK_DATA: 'todayTaskData',
      TODAY_REVIEW_DATA: 'todayReviewData',
      USER_CHALLENGE_STATS: 'userChallengeStats',
      USER_MAGIC_COINS: 'userMagicCoins',
      USER_CHALLENGE_RECORDS: 'userChallengeRecords',
      BOOKS_DOWNLOAD_TIMESTAMP_KEY: 'booksDownloadTimestamp',
      BUILTIN_BOOKS_CACHE_KEY: 'builtinBooksCache',
      LAST_LEARNED_WORD_INFO: 'lastLearnedWordInfo',
      TODAY_LEARNING_EVENTS: 'todayLearningEvents',
      TASK_SETTINGS: 'taskSettings',
      // 不再使用RECENT_BOOK_ID，改为通过wordDataManager.getActiveBookId()获取激活词书
      WORD_GAME_STATS: 'wordGameStats',
      RECENT_WORD_GAMES: 'recentWordGames',
      USER_INFO: 'userInfo',
      TODAY_TASK_EXTRA: 'todayTaskExtra',
      LEARNING_UNITS: 'learningUnits',
      IMPORT_HISTORY: 'importHistory',
      TOUR_GUIDE_COMPLETED: 'tour_guide_completed',
      CLAIMED_TASK_REWARDS: 'claimedTaskRewards',
      WORD_LEARNING_INFO_DATA: 'wordLearningInfoData',
      AI_CHAT_HISTORY: 'aiChatHistory'
    };
    
    // 定义日志级别
    this.LOG_LEVEL = {
      NONE: 0,
      ERROR: 1,
      WARN: 2,
      INFO: 3,
      DEBUG: 4
    };
    
    // 当前日志级别
    this.currentLogLevel = this.LOG_LEVEL.INFO;
    
    // 防抖相关属性 - 避免短时间频繁检查缓存空间
    this.checkStorageTimeoutId = null;
    this.checkStorageDebounceDelay = 1000; // 1000毫秒防抖延迟
  };
  
  /**
   * 统一的存储设置方法
   * @param {string} key - 存储键名
   * @param {any} data - 要存储的数据
   * @param {boolean} [checkSpace=true] - 是否在存储前检查空间
   * @returns {boolean} 存储是否成功
   */
  setStorage(key, data, checkSpace = true) {
    try {
      // 可选的空间检查
      if (checkSpace) {
        this.checkStorageSpace();
      }
      
      // 存储数据
      wx.setStorageSync(key, data);
      
      // 记录日志
      this._log(`存储数据成功: ${key}`, this.LOG_LEVEL.INFO);
      return true;
    } catch (error) {
      // 记录错误
      this._log(`存储数据失败: ${key}, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
      
      // 尝试处理存储失败
      this._handleStorageError(key, data, error);
      return false;
    }
  }
  
  /**
   * 统一的存储获取方法
   * @param {string} key - 存储键名
   * @param {any} [defaultValue=null] - 默认值
   * @returns {any} 获取的数据或默认值
   */
  getStorage(key, defaultValue = null) {
    try {
      const data = wx.getStorageSync(key);
      
      // 如果获取的数据为undefined，返回默认值
      const result = data === undefined ? defaultValue : data;
      
      // 记录日志（DEBUG级别）
      this._log(`获取数据: ${key}, 是否存在: ${data !== undefined}`, this.LOG_LEVEL.DEBUG);
      return result;
    } catch (error) {
      // 记录错误
      this._log(`获取数据失败: ${key}, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
      return defaultValue;
    }
  }
  
  /**
   * 统一的存储删除方法
   * @param {string} key - 存储键名
   * @returns {boolean} 删除是否成功
   */
  removeStorage(key) {
    try {
      wx.removeStorageSync(key);
      
      // 记录日志
      this._log(`删除数据成功: ${key}`, this.LOG_LEVEL.INFO);
      return true;
    } catch (error) {
      // 记录错误
      this._log(`删除数据失败: ${key}, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
      return false;
    }
  }
  
  /**
   * 清除所有存储数据
   * @returns {boolean} 清除是否成功
   */
  clearStorage() {
    try {
      wx.clearStorageSync();
      
      // 记录日志
      this._log('清除所有存储数据成功', this.LOG_LEVEL.INFO);
      return true;
    } catch (error) {
      // 记录错误
      this._log(`清除存储数据失败, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
      return false;
    }
  }
  
  /**
   * 批量设置存储数据
   * @param {Object} dataObject - 键值对对象
   * @param {boolean} [checkSpace=true] - 是否在存储前检查空间
   * @returns {Object} 每个键的存储结果
   */
  setStorageBatch(dataObject, checkSpace = true) {
    const results = {};
    
    try {
      // 可选的空间检查
      if (checkSpace) {
        this.checkStorageSpace();
      }
      
      // 批量存储
      Object.keys(dataObject).forEach(key => {
        try {
          wx.setStorageSync(key, dataObject[key]);
          results[key] = true;
          this._log(`批量存储数据成功: ${key}`, this.LOG_LEVEL.DEBUG);
        } catch (error) {
          results[key] = false;
          this._log(`批量存储数据失败: ${key}, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
        }
      });
    } catch (error) {
      this._log(`批量存储过程发生错误: ${error.message}`, this.LOG_LEVEL.ERROR);
    }
    
    return results;
  }
  
  /**
   * 批量获取存储数据
   * @param {Array<string>} keys - 键名数组
   * @returns {Object} 键值对结果
   */
  getStorageBatch(keys) {
    const results = {};
    
    keys.forEach(key => {
      try {
        results[key] = wx.getStorageSync(key);
      } catch (error) {
        this._log(`批量获取数据失败: ${key}, 错误: ${error.message}`, this.LOG_LEVEL.ERROR);
        results[key] = null;
      }
    });
    
    return results;
  }
  
  /**
   * 处理存储错误
   * @private
   * @param {string} key - 存储键名
   * @param {any} data - 要存储的数据
   * @param {Error} error - 错误对象
   */
  _handleStorageError(key, data, error) {
    // 如果是存储空间不足的错误，尝试清理一些非关键数据
    if (error.message.includes('storage') || error.message.includes('内存')) {
      console.warn('存储错误可能是由于空间不足，尝试清理缓存...');
      
      // 尝试清理非关键数据
      this.cleanNonCriticalData();
      
      // 再次尝试存储
      try {
        wx.setStorageSync(key, data);
        this._log(`清理后存储数据成功: ${key}`, this.LOG_LEVEL.INFO);
      } catch (retryError) {
        this._log(`清理后存储数据仍然失败: ${key}, 错误: ${retryError.message}`, this.LOG_LEVEL.ERROR);
        
        // 显示用户提示
        wx.showToast({
          title: '存储失败，请清理缓存',
          icon: 'none'
        });
      }
    }
  }
  
  /**
   * 清理非关键数据
   * @private
   */
  cleanNonCriticalData() {
    try {
      // 可以清理的非关键数据键名列表
      const nonCriticalKeys = [
        this.STORAGE_KEYS.BUILTIN_BOOKS_CACHE_KEY
        // 可以根据实际需要添加更多非关键数据键名
      ];
      
      nonCriticalKeys.forEach(key => {
        try {
          wx.removeStorageSync(key);
          this._log(`清理非关键数据: ${key}`, this.LOG_LEVEL.INFO);
        } catch (error) {
          this._log(`清理非关键数据失败: ${key}`, this.LOG_LEVEL.ERROR);
        }
      });
    } catch (error) {
      this._log(`清理非关键数据过程发生错误: ${error.message}`, this.LOG_LEVEL.ERROR);
    }
  }
  
  /**
   * 记录日志
   * @private
   * @param {string} message - 日志消息
   * @param {number} level - 日志级别
   */
  _log(message, level) {
    if (level <= this.currentLogLevel) {
      switch (level) {
        case this.LOG_LEVEL.ERROR:
          console.error(`[StorageManager ERROR] ${message}`);
          break;
        case this.LOG_LEVEL.WARN:
          console.warn(`[StorageManager WARN] ${message}`);
          break;
        case this.LOG_LEVEL.INFO:
          console.log(`[StorageManager INFO] ${message}`);
          break;
        case this.LOG_LEVEL.DEBUG:
          console.debug(`[StorageManager DEBUG] ${message}`);
          break;
        default:
          break;
      }
    }
  }
  
  /**
   * 设置日志级别
   * @param {number} level - 日志级别
   */
  setLogLevel(level) {
    this.currentLogLevel = level;
  }

  /**
   * 检查缓存空间是否即将耗尽（带防抖机制，确保短时间内多次调用只执行最后一次）
   * @param {Function} onSpaceLow - 缓存空间不足时的回调函数
   * @returns {Promise<Object>} 缓存信息对象
   */
  checkStorageSpace(onSpaceLow) {
    return new Promise((resolve, reject) => {
      // 清除之前的定时器（防抖核心逻辑）
      if (this.checkStorageTimeoutId) {
        clearTimeout(this.checkStorageTimeoutId);
        this._log('清除之前的缓存空间检查定时器（防抖）', this.LOG_LEVEL.DEBUG);
      }
      
      // 设置新的定时器
      this.checkStorageTimeoutId = setTimeout(() => {
        try {
          this._log('执行缓存空间检查', this.LOG_LEVEL.DEBUG);
          // 获取缓存信息
          wx.getStorageInfo({  
            success: (res) => {
              // 计算缓存使用百分比
              const usedPercentage = (res.currentSize / res.limitSize) * 100;
              this._log(`当前缓存使用情况: ${res.currentSize}KB / ${res.limitSize}KB (${usedPercentage.toFixed(2)}%)`, this.LOG_LEVEL.INFO);
              
              // 如果缓存使用超过80%，执行回调或提示用户
              if (usedPercentage > 80) {
                if (typeof onSpaceLow === 'function') {
                  onSpaceLow(usedPercentage, res);
                } else {
                  // 默认提示行为
                  this._showSpaceLowDialog(usedPercentage);
                }
              }
              
              resolve(res);
            },
            fail: (err) => {
              this._log('获取缓存信息失败: ' + err.message, this.LOG_LEVEL.ERROR);
              reject(err);
            }
          });
        } catch (error) {
          this._log('检查缓存空间时发生错误: ' + error.message, this.LOG_LEVEL.ERROR);
          reject(error);
        }
      }, this.checkStorageDebounceDelay);
    });
  }

  /**
   * 显示缓存空间不足对话框
   * @private
   * @param {number} usedPercentage - 缓存使用百分比
   */
  _showSpaceLowDialog(usedPercentage) {
    wx.showModal({
      title: '缓存空间不足',
      content: `当前缓存空间使用已达${usedPercentage.toFixed(0)}%，可能影响应用性能。是否清理单词同步数据？`,
      success: (result) => {
        if (result.confirm) {
          console.log('用户确认清理单词同步数据');
          this.cleanWordDictionarySyncFields();
        }
      }
    });
  }

  /**
   * 清理wordDictionary缓存中的同步字段，但保留原始字段
   * @returns {Promise<Object>} 清理结果对象
   */
  cleanWordDictionarySyncFields() {
    return new Promise((resolve, reject) => {
      try {
        // 从WordDataManager获取所有单词数据
        const wordDataManager = require('./wordDataManager').getInstance();
        const allWords = wordDataManager.getAllWords();
        
        let cleanedWordsCount = 0;
        let preservedWordsCount = 0;
        
        // 清理每个单词的同步字段
        Object.keys(allWords).forEach(wordId => {
          const word = allWords[wordId];
          if (word) {
            // 创建新对象，只保留原始字段
            const cleanedWord = {};
            this.ORIGINAL_WORD_FIELDS.forEach(field => {
              if (word[field] !== undefined) {
                cleanedWord[field] = word[field];
              }
            });
            
            // 检查是否有同步字段被清理
            const hasSyncFields = Object.keys(word).some(key => !this.ORIGINAL_WORD_FIELDS.includes(key));
            if (hasSyncFields) {
              allWords[wordId] = cleanedWord;
              cleanedWordsCount++;
            } else {
              preservedWordsCount++;
            }
          }
        });
        
        // 保存清理后的单词数据，使用false跳过空间检查以避免循环调用
        this.setStorage(this.STORAGE_KEYS.WORD_DICTIONARY, allWords, false);
        
        // 显示清理成功的提示
        wx.showToast({
          title: `清理完成\n共清理${cleanedWordsCount}个单词的同步数据`,
          icon: 'success',
          duration: 2000
        });
        
        console.log(`清理单词同步数据完成: 清理${cleanedWordsCount}个单词，${preservedWordsCount}个单词无同步数据`);
        
        // 重新获取缓存信息，显示清理后的使用情况
        wx.getStorageInfo({  
          success: (res) => {
            const usedPercentage = (res.currentSize / res.limitSize) * 100;
            console.log(`清理后缓存使用情况: ${res.currentSize}KB / ${res.limitSize}KB (${usedPercentage.toFixed(2)}%)`);
            
            resolve({
              success: true,
              cleanedWordsCount,
              preservedWordsCount,
              storageInfo: res
            });
          },
          fail: () => {
            resolve({
              success: true,
              cleanedWordsCount,
              preservedWordsCount
            });
          }
        });
      } catch (error) {
        console.error('清理单词同步数据时发生错误:', error);
        wx.showToast({
          title: '清理失败',
          icon: 'error'
        });
        reject(error);
      }
    });
  }

  /**
   * 获取当前缓存使用统计
   * @returns {Promise<Object>} 缓存统计信息
   */
  getStorageStats() {
    return new Promise((resolve, reject) => {
      wx.getStorageInfo({
        success: (res) => {
          const stats = {
            currentSize: res.currentSize,
            limitSize: res.limitSize,
            usedPercentage: (res.currentSize / res.limitSize) * 100,
            keys: res.keys,
            keyCount: res.keys.length
          };
          resolve(stats);
        },
        fail: (err) => {
          console.error('获取缓存统计失败:', err);
          reject(err);
        }
      });
    });
  }

  /**
   * 获取存储管理器的单例实例
   * @returns {StorageManager} 存储管理器实例
   */
  static getInstance() {
    if (!instance) {
      instance = new StorageManager();
    }
    return instance;
  }
}

// 导出类和单例实例
module.exports = {
  StorageManager,
  getInstance: StorageManager.getInstance
};

// 同时设置默认导出为单例实例
module.exports.default = StorageManager.getInstance();

// 保持向后兼容性，仍提供instance属性
Object.defineProperty(module.exports, 'instance', {
  get: function() {
    return StorageManager.getInstance();
  },
  enumerable: true,
  configurable: true
});